// 版权归GoFrame作者(https://goframe.org)所有。保留所有权利。
//
// 本源代码形式受MIT许可证条款约束。
// 如果未随本文件一同分发MIT许可证副本，
// 您可以在https://github.com/gogf/gf处获取。
// md5:a9832f33b234e3f3

package json类

import (
	"reflect"

	"gitee.com/go_888/extends/goframe/internal/reflection"
	"gitee.com/go_888/extends/goframe/internal/rwmutex"
	gconv "gitee.com/go_888/extends/goframe/gconv"
)

// New 使用任何类型的`data`创建一个Json对象，但为了数据访问的原因，`data`应该是map或slice，
// 否则将失去意义。
//
// 参数`safe`指定是否在并发安全的上下文中使用此Json对象，默认值为false。
// md5:b84f401db24e69d8
func X创建(值 interface{}, 并发安全 ...bool) *X结构_Json {
	return X创建并按类型标签(值, string(X常量_ContentTypeJson), 并发安全...)
}

// NewWithTag 创建一个Json对象，可以包含任何类型的`data`，但出于数据访问的原因，`data`应该是一个map或切片，否则将没有意义。
// 
// 参数`tags`用于指定结构体转换为map的优先标签，多个标签之间用逗号分隔。
// 
// 参数`safe`表示是否在并发安全上下文中使用这个Json对象，默认为false。
// md5:2558f08f4f082a16
func X创建并按类型标签(值 interface{}, 类型标签 string, 并发安全 ...bool) *X结构_Json {
	option := X结构_选项{
		Tags: 类型标签,
	}
	if len(并发安全) > 0 && 并发安全[0] {
		option.Safe = true
	}
	return X创建并按选项(值, option)
}

// X创建并按选项使用任何类型的'data'创建一个Json对象，但出于数据访问的原因，`data`应该是map或切片，否则将没有意义。
// md5:48be1828a6556518
func X创建并按选项(值 interface{}, 选项 X结构_选项) *X结构_Json {
	var j *X结构_Json
	switch result := 值.(type) {
	case []byte:
		if r, err := loadContentWithOptions(result, 选项); err == nil {
			j = r
			break
		}
		j = &X结构_Json{
			p:  &值,
			c:  byte(defaultSplitChar),
			vc: false,
		}
	case string:
		if r, err := loadContentWithOptions([]byte(result), 选项); err == nil {
			j = r
			break
		}
		j = &X结构_Json{
			p:  &值,
			c:  byte(defaultSplitChar),
			vc: false,
		}
	default:
		var (
			pointedData interface{}
			reflectInfo = reflection.OriginValueAndKind(值)
		)
		switch reflectInfo.OriginKind {
		case reflect.Slice, reflect.Array:
			pointedData = gconv.X取any数组(值)

		case reflect.Map:
			pointedData = gconv.X取Map_递归(值, 选项.Tags)

		case reflect.Struct:
			if v, ok := 值.(iVal); ok {
				return X创建并按选项(v.X取值(), 选项)
			}
			pointedData = gconv.X取Map_递归(值, 选项.Tags)

		default:
			pointedData = 值
		}
		j = &X结构_Json{
			p:  &pointedData,
			c:  byte(defaultSplitChar),
			vc: false,
		}
	}
	j.mu = rwmutex.Create(选项.Safe)
	return j
}
